package com.caishi.lkx.common.util;

import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.*;
import com.caishi.lkx.common.sms.AliyunSmsModel;
import com.caishi.lkx.common.sms.SmsGroupPlugins;
import com.zzw.common.AliyunPluginsAuto;
import com.zzw.common.exception.BizException;
import com.zzw.common.exception.BizRuntimeException;
import com.zzw.common.sms.AliyunSmsPlugins;
import com.zzw.common.sms.SmsSendResult;
import com.zzw.common.sms.SmsStatus;
import com.caishi.lkx.common.NacosDiamond;
import com.caishi.lkx.common.context.UserContext;
import com.caishi.lkx.common.ienum.PlatformType;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author by keray
 * date:2021/4/9 10:14 上午
 * SignName 短信签名名称
 * TemplateCode 短信模板ID
 * TemplateParam 短信模板变量对应的实际值，JSON格式。
 */
@ConditionalOnBean(AliyunSmsPlugins.class)
@Configuration
@AutoConfigureAfter(AliyunPluginsAuto.class)
@ConfigurationProperties(prefix = "aliyun.sms.tmpcode")
public class SmsUtilService implements NacosDiamond {
    @Resource
    private UserContext userContext;

    public enum SmsCodeType {
        login("phone-login-code:"), // 登录验证码
        register("phone-register-code:"), // 注册验证码
        resetPass("phone-reset-pass-code:"), // 重置密码验证码
        forgetPass("phone-forget-pass-code:"),// 忘记密码验证码
        bindPhone("phone-bind-phone-code:"),// 新绑定手机号验证码
        resetBindPhone("reset-bind-phone-code:"),// 更换绑定手机号验证码
        liveAppointNotification("live-appoint-notification:")
        ;

        @Getter
        final String key;

        SmsCodeType(String s) {
            this.key = s;
        }
    }

    @Value("${spring.profiles.active}")
    private String active;
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private SmsGroupPlugins smsPlugins;


    @Getter
    @Setter
    private Map<String, String> tmpMap;


    /**
     * <p>
     * <h3>作者 keray</h3>
     * <h3>时间： 2021/4/9 10:17 上午</h3>
     * 发送验证码短信
     * </p>
     *
     * @param phone       手机号
     * @param code        验证码
     * @param smsCodeType 验证码类型
     * @return <p> {@link } </p>
     * @throws
     */
    public void sendCode(String phone, String code, SmsCodeType smsCodeType, long ms, AliyunSmsModel smsConfig) throws BizException {
        String tmp = tmpMap.get(smsCodeType.name());
        PlatformType platformType = userContext.currentPlatform();
        MapBuilder<String, Object> mapBuilder = MapUtil.<String, Object>builder()
                .put("TemplateCode", tmp)
                .put("TemplateParam", MapUtil.builder("code", code).build());
        SmsStatus result = smsPlugins.send(phone, mapBuilder.build(), smsConfig);
        if (result == SmsStatus.fail) {
            throw new BizRuntimeException("短信发送失败，请稍后再试！");
        }
        redisTemplate.opsForValue().set(key(smsCodeType, phone), code, ms, TimeUnit.MILLISECONDS);
    }

    public void sendCode(String phone, SmsCodeType smsCodeType, long ms, AliyunSmsModel smsConfig) throws BizException {
        String code = RandomUtil.randomNumbers(6);
        sendCode(phone, code, smsCodeType, ms, smsConfig);
    }

    public void sendCode(String phone, SmsCodeType smsCodeType, AliyunSmsModel smsConfig) throws BizException {
        sendCode(phone, smsCodeType, 10 * 60 * 1000, smsConfig);
    }


    public boolean checkCode(String phone, String code, SmsCodeType smsCodeType) {
        if (!"pro".equals(active) && "888888".equals(code)) return true;
        return StrUtil.isNotBlank(code) && code.equals(redisTemplate.opsForValue().get(key(smsCodeType, phone)));
    }

    protected String key(SmsCodeType smsCodeType, String phone) {
        return smsCodeType.getKey() + phone;
    }

    public List<Future<SmsSendResult>> sendMsgAsync(List<String> phoneList, String msg, SmsCodeType smsCodeType, AliyunSmsModel smsConfig) {
        String tmp = tmpMap.get(smsCodeType.name());
        return smsPlugins.sendAsync(phoneList, MapUtil.<String, Object>builder()
                .put("TemplateCode", tmp)
                .put("TemplateParam", msg)
                .build(), smsConfig);
    }

    // datas列表的map包含手机号，名字，时间
    public FutureTask<SendBatchSmsResponse> sendLiveNotification(List<Map<String,Object>> datas, SmsCodeType smsCodeType, AliyunSmsModel smsConfig) throws Exception {
        String tmp = tmpMap.get(smsCodeType.name());
//              .put("TemplateParam", MapUtil.builder("name", data.get("name"))
//                        .put("time",data.get("time"))
        Map<String, Object> params = MapUtil.<String, Object>builder().build();
        JSONArray phoneNumberJson = new JSONArray();
        JSONArray signNameJson = new JSONArray();
        JSONArray templateParamJson = new JSONArray();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        for(var i=0;i<datas.size();i++){
            var data = datas.get(i);
            phoneNumberJson.add(data.get("phoneNumber"));
            signNameJson.add(smsConfig.getSignName());
            templateParamJson.add(
                    MapBuilder.create()
                            .put("name", data.get("name"))
                            .put("time",((LocalDateTime) data.get("time")).format(formatter))
                            .build());
        }


        Client client = smsPlugins.getClient(smsConfig);
        // 异步发送短信获取结果
        return new FutureTask<SendBatchSmsResponse>(() -> {
           return client.sendBatchSms(new SendBatchSmsRequest()
                   .setTemplateCode(tmp)
                   .setPhoneNumberJson(phoneNumberJson.toJSONString())
                   .setSignNameJson(signNameJson.toJSONString())
                   .setTemplateParamJson(templateParamJson.toJSONString())
           );
        });



    }
    public AddSmsTemplateResponseBody createTemplate(AliyunSmsModel smsConfig) throws Exception {
        Client client = smsPlugins.getClient(smsConfig);
        AddSmsTemplateResponse addSmsTemplateResponse = client.addSmsTemplate(new AddSmsTemplateRequest()
                .setTemplateName("直播预约通知")
                .setTemplateContent("亲爱的${name},您预约的直播将于${time}直播,请合理安排时间。")
                .setRemark("直播预约通知")
                .setTemplateType(1));
        return addSmsTemplateResponse.getBody();
    }
    public QuerySmsTemplateListResponseBody getTemplates(AliyunSmsModel smsConfig) throws Exception {
        Client client = smsPlugins.getClient(smsConfig);
        QuerySmsTemplateListResponse querySmsTemplateListResponse = client.querySmsTemplateList(new QuerySmsTemplateListRequest()
                .setPageIndex(1));
        return querySmsTemplateListResponse.getBody();
    }
}
